package model

import (
	"fmt"
	"github.com/gomodule/redigo/redis"
	"github.com/jinzhu/gorm"
	_ "github.com/jinzhu/gorm/dialects/mysql"
	"github.com/lexkong/log"
	"github.com/spf13/viper"
)

type Database struct {
	Self   *gorm.DB
	Docker *gorm.DB
	Redis  *Redis
}

var DB *Database

func openDB(username, password, addr, name string) *gorm.DB {
	config := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8&parseTime=%t&loc=%s",
		username,
		password,
		addr,
		name,
		true,
		"Local",
	)
	log.Infof(config)
	db, err := gorm.Open("mysql", config)
	if err != nil {
		log.Errorf(err, "Database connection failed. Database name: %s", name)
	}
	setupDB(db)
	return db
}

func setupDB(db *gorm.DB) {
	db.LogMode(viper.GetBool("gormlog"))
	db.DB().SetMaxIdleConns(0) // 用于设置闲置的连接数.设置闲置的连接数则当开启的一个连接使用完成后可以放在池里等候下一次使用。
}

// used for cli
func InitSelfDB() *gorm.DB {
	return openDB(viper.GetString("db.username"),
		viper.GetString("db.password"),
		viper.GetString("db.addr"),
		viper.GetString("db.name"))
}

func GetSelfDB() *gorm.DB {
	return InitSelfDB()
}

func InitDockerDB() *gorm.DB {
	return openDB(viper.GetString("docker_db.username"),
		viper.GetString("docker_db.password"),
		viper.GetString("docker_db.addr"),
		viper.GetString("docker_db.name"))
}
func GetDockerDB() *gorm.DB {
	return InitDockerDB()
}

func (db *Database) Init() {
	DB = &Database{
		Self: GetSelfDB(),
		//Docker: GetDockerDB(),
		Redis: OpenRedis(),
	}
}

func (db *Database) Close() {
	DB.Self.Close()
	//DB.Docker.Close()
	DB.Redis.Close()
}

type Redis struct {
	conn redis.Conn
}

func OpenRedis() *Redis {
	//conn, err := redis.Dial("tcp", viper.GetString("redis.addr"))
	conn, err := redis.Dial("tcp", "127.0.0.1:3306")
	if err != nil {
		log.Errorf(err, "Redis connection failed. err : %s")
	}
	return &Redis{conn: conn}
}

func (r Redis) Close() {
	r.conn.Close()
}

func (r Redis) SET(key string, value string) error {
	_, err := r.conn.Do("SET", key, value)
	return err
}

func (r Redis) SETEX(key string, value string, exp int) error {
	_, err := r.conn.Do("SET", key, value, "EX", exp)
	return err
}

func (r Redis) Get(key string) (value string, err error) {
	return redis.String(r.conn.Do("GET", key))
}

func (r Redis) DELETE(key string) (err error) {
	_, err = r.conn.Do("DEL", key)
	return err
}
